<?php
/*
 * @Author: Wulala
 * @Date: 2025-04-08 11:46:09
 * @LastEditTime: 2025-04-11 14:36:03
 * @LastEditors: Wulala
 * @Description: 
 * @FilePath: \exchange\app\api\service\SignService.php
 * 可以输入预定的版权声明、个性签名、空行等
 */

namespace app\api\service;


// 验签服务类
/**
 * 模仿微信的签名验证类
 */
class SignService
{
    /**
     * 生成签名
     * @param array $data 待签名数据
     * @param string $key 密钥
     * @param string $signType 签名类型 MD5|HMAC-SHA256
     * @return string 签名
     */
    public static function generateSign(array $data, string $key, string $signType = 'MD5'): string
    {
        // 过滤空值
        $data = array_filter($data);
        
        // 参数按字典序排序
        ksort($data);
        
        // 拼接成URL参数形式
        $string = self::toUrlParams($data);
        
        // 拼接API密钥
        $string .= '&key=' . $key;
        
        // 生成签名
        if ($signType === 'HMAC-SHA256') {
            $sign = hash_hmac('sha256', $string, $key);
        } else {
            $sign = md5($string);
        }
        
        return strtoupper($sign);
    }
    
    /**
     * 验证签名
     * @param array $data 待验证数据
     * @param string $key 密钥
     * @param string $signType 签名类型 MD5|HMAC-SHA256
     * @return bool 验证结果
     */
    public static function verifySign(array $data, string $key, string $signType = 'MD5'): bool
    {
        if (!isset($data['sign'])) {
            return false;
        }
        
        $sign = $data['sign'];
        unset($data['sign']);
        
        $calculatedSign = self::generateSign($data, $key, $signType);
        
        return $sign === $calculatedSign;
    }
    
    /**
     * 将参数数组转换为URL参数字符串
     * @param array $data
     * @return string
     */
    private static function toUrlParams(array $data): string
    {
        $buff = '';
        foreach ($data as $k => $v) {
            if ($k !== 'sign' && $v !== '' && !is_array($v)) {
                $buff .= $k . '=' . $v . '&';
            }
        }
        return rtrim($buff, '&');
    }

}